package net.chasing.retrofit.util;

import androidx.annotation.NonNull;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;

public class LoggerInterceptor implements Interceptor {
    @NonNull
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        //打印请求信息
        RetrofitLog.i("retrofit request url:" + request.url());
        RetrofitLog.i("retrofit request method:" + request.method());
        Headers headers = request.headers();
        RetrofitLog.i("retrofit request headers:" + headers);
        String body = bodyToString(request);
        RetrofitLog.i("retrofit request body:" + body);

        //记录请求耗时
        long startNs = System.nanoTime();
        Response response;
        try {
            //发送请求
            response = chain.proceed(request);
        } catch (Exception e) {
            RetrofitLog.i("retrofit request proceed exception:" + e.getMessage());
            // 需要通过抛出异常，让Okhttp的责任链进行下一环节，如果直接return null则会导致应用崩溃
            throw e;
        }
        try {
            long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
            //打印请求耗时
            RetrofitLog.i("retrofit request 耗时:" + tookMs + "ms");
            //使用response获得headers(),可以更新本地Cookie。
            //获得返回的body，注意此处不要使用responseBody.string()获取返回数据，原因在于这个方法会消耗返回结果的数据(buffer)
            ResponseBody responseBody = response.body();
            if (responseBody != null) {
                //为了不消耗buffer，我们这里使用source先获得buffer对象，然后clone()后使用
                BufferedSource source = responseBody.source();
                source.request(Long.MAX_VALUE); // Buffer the entire body.
                //获得返回的数据
                Buffer buffer = source.getBuffer();
                //使用前clone()下，避免直接消耗，避免打印大的数据，会引发内存问题
                if (buffer.size() < 1024 * 1000) {
                    String info = buffer.clone().readString(StandardCharsets.UTF_8);
                    RetrofitLog.i("retrofit request response:" + info);
                }
            }
        } catch (Exception e) {
            RetrofitLog.i("retrofit request response deal exception:" + e.getMessage());
        }
        return response;
    }

    private static String bodyToString(final Request request) {

        try {
            final Request copy = request.newBuilder().build();
            final Buffer buffer = new Buffer();
            RequestBody body = copy.body();
            if (body != null)
                body.writeTo(buffer);
            return buffer.readUtf8();
        } catch (IOException e) {
            return "error";
        }
    }
}
